[02] Anskaffelse og innlasting av tekst
Martin Søyland <martin.soyland@stv.uio.no>
data[rader, kolonner]tibble(stortingscrape::cases$root) %>% # Henter ut data fra stortingscrape
select(id, status, type, title_short) %>% # Trekker ut relevante variabler
slice_sample(n = 5) # Viser 5 tilfeldige enheter## # A tibble: 5 × 4
## id status type title_short
## <chr> <chr> <chr> <chr>
## 1 80332 til_behandling alminneligsak Grunnlovsforslag om ny § 107 (rett til bol…
## 2 79518 behandlet alminneligsak Redegjørelse av utenriksministeren om vikt…
## 3 79329 behandlet budsjett Innstilling fra finanskomiteen om Endringe…
## 4 79932 behandlet alminneligsak Representantforslag om å sørge for at alle…
## 5 77424 behandlet budsjett Endringar i statsbudsjettet 2019 under Olj…
| Format | Står for | R-funksjon |
|---|---|---|
| .csv | Comma Separated Values | read.csv //
readr::read_csv() |
| .txt | Text | readLines() //
textreadr::read_document() |
| .xlsx | Excel | readxl::read_xlsx() |
| .html | HyperText Markup Language | rvest::read:html() |
| .xml | Extensible Markup Language | rvest::read:html() |
| .json | JavaScript Object Notation | jsonlite::read_json() |
| .dta | Stata | haven::read_dta() |
| .sav | SPSS | haven::read_sav() |
| … | Og tusen andre formater… | …med egne R-pakker og funksjoner |
Application Programming Interface:
[05] Bruke API (Stortinget) (uke 38)
Tilfeldig side fra Statens vegvesen
## <?xml version="1.0" encoding="utf8"?>
## <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:skos="http://www.w3.org/2004/02/skos/core#">
## <rdf:Description rdf:about="https://psi.norge.no/los/ord/parkering-og-hvileplasser">
## <rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
## <skos:inScheme rdf:resource="https://psi.norge.no/los/ontologi/ord"/>
## <skos:prefLabel xml:lang="nn">Parkering</skos:prefLabel>
## <skos:prefLabel xml:lang="nb">Parkering og hvileplasser</skos:prefLabel>
## <skos:prefLabel xml:lang="en">Parking and rest area</skos:prefLabel>
## <skos:hiddenLabel xml:lang="nb">Avgiftsparkering</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Avgiftsparkering</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Innfartsparkering</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Innfartsparkering</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringsavgift</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsavgift</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringsbot</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsbot</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringsgebyr</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsgebyr</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringskort</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringskort</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsløyve</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringsløyve</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsløyve</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringsplass</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Parkeringsplass</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Parkeringstillatelse</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Rasteplassar</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Rasteplasser</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nb">Utfartsparkering</skos:hiddenLabel>
## <skos:hiddenLabel xml:lang="nn">Utfartsparkering</skos:hiddenLabel>
## <skos:note xml:lang="nn">Det skal vere eitt felles regelverk for all parkeringsverksemd. Regelverket skal syte for lik skilting og like reaksjonar ved brot på føresegnene. Det er også ei obligatorisk godkjenningsordning som gjeld både for kommunar, private parkeringsselskap og andre.</skos:note>
## <skos:note xml:lang="nb">Parkeringstillatelser, parkeringsgebyr, regelverk for gateparkering, parkering for forflytningshemmede, klage på parkeringsbot, betaling av parkeringsbot.</skos:note>
## <skos:broader rdf:resource="https://psi.norge.no/los/tema/mobilitetstilbud"/>
## <skos:broader rdf:resource="https://psi.norge.no/los/tema/veg-og-vegregulering"/>
## <skos:broader rdf:resource="https://psi.norge.no/los/tema/yrkestransport"/>
## </rdf:Description>
## </rdf:RDF>
Skandinaviske land blir nevnt oftere enn andre land i NOUer fra Utenriksdepartementet
library(rvest)
library(stringr)
# rot-url for regjeringen.no
base_url <- "https://www.regjeringen.no"
# Laster ned siden med alle NOUer fra UD (atm 7 stk)
## str_c(base_url, "no/dokument/nou-ar/id1767/?ownerid=833") %>%
## download.file(., destfile = "./scrape/base.html")
##
# Trekker ut linkene til hver NOU
nou_links <- read_html("./scrape/base.html") %>%
html_elements("li > h2 > a[data-hitid]") %>%
html_attr("href")
paste0(base_url, nou_links)## [1] "https://www.regjeringen.no/no/dokumenter/nou-2016-8/id2503028/"
## [2] "https://www.regjeringen.no/no/dokumenter/nou-2012-2/id669368/"
## [3] "https://www.regjeringen.no/no/dokumenter/nou-2009-19/id571718/"
## [4] "https://www.regjeringen.no/no/dokumenter/nou-2008-14/id525832/"
## [5] "https://www.regjeringen.no/no/dokumenter/nou-2003-32/id149022/"
## [6] "https://www.regjeringen.no/no/dokumenter/nou-1995-5/id139818/"
## [7] "https://www.regjeringen.no/no/dokumenter/nou-1994-9/id139452/"
# Laster ned forsiden til hver NOU
for(i in nou_links){
# Trekker ut dokument-id
tmp_id <- str_extract(i, "id[0-9]+")
# Laster ned forsiden til NOU i
str_c(base_url, i) %>%
download.file(., destfile = str_c( "./scrape/nou_forside/",
tmp_id,
".html"))
# Legger til litt tilfeldig søvn
Sys.sleep(2 + abs(rnorm(1, 0)))
# Printer en beskjed til console om at i nå er ferdig
message(str_c(
"Ferdig med: ",
tmp_id,
"\n"
))
}## [1] "id139452.html" "id139818.html" "id149022.html" "id2503028.html"
## [5] "id525832.html" "id571718.html" "id669368.html"
# Les inn hver forsidefil med read_html()
nou_forsider <- lapply(
list.files("./scrape/nou_forside/", full.names = TRUE),
read_html
)
# Viser første listeelement
nou_forsider[[1]]## {html_document}
## <html class="no-js" lang="no">
## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8 ...
## [2] <body class="page-horing ">\r\n\r\n<!-- There is a copy of this in /Error ...
.pdf for alle NOUene.pdf-filene# Prosesserer hvert listeelement
nou_pdf_links <- sapply(nou_forsider, function(x){
tmp_content_link <- x %>% # Trekk ut listeelement x
html_elements("a[title]") %>% # Trekk ut html nodene "a" som har egenskapen "title"
html_attr("href") # Trekk ut teksten til egenskapen "href"
# Trekk ut bare de linkene som inneholder ".pdf" på slutten av strengen
tmp_content_link %>%
magrittr::extract(str_detect(., "\\.pdf$"))
})
# Vis linkene
nou_pdf_links## [1] "/contentassets/bee23e85425c4fca84346e100bf745c7/no/pdfa/nou199419940009000dddpdfa.pdf"
## [2] "/contentassets/3a80ddef404745e5be000a9f58a762a1/no/pdfa/nou199519950005000dddpdfa.pdf"
## [3] "/contentassets/28ed358f13704ed2bb3c2a7f13a02be9/no/pdfs/nou200320030032000dddpdfs.pdf"
## [4] "/contentassets/09faceca099c4b8bac85ca8495e12d2d/no/pdfs/nou201620160008000dddpdfs.pdf"
## [5] "/contentassets/9b801d1fe4804a9a9e30d8d621a3b021/no/pdfs/nou200820080014000dddpdfs.pdf"
## [6] "/contentassets/0a903cdd09fc423ab21f43c3504f466a/no/pdfs/nou200920090019000dddpdfs.pdf"
## [7] "/contentassets/5d3982d042a2472eb1b20639cd8b2341/no/pdfs/nou201220120002000dddpdfs.pdf"
# Laster ned pdf til hver NOU
for(i in nou_pdf_links){
# Trekker ut dokument-id
tmp_id <- str_extract(i, "nou(.*?)\\.pdf$")
# Laster ned forsiden til NOU i
str_c(base_url, i) %>%
download.file(., destfile = str_c("./scrape/nou_pdf/",
tmp_id))
# Legger til litt tilfeldig søvn
Sys.sleep(2 + abs(rnorm(1, 0)))
# Printer en beskjed til console om at i nå er ferdig
message(str_c(
"Ferdig med: ",
tmp_id,
"\n"
))
}
# Lister opp filene
list.files("./scrape/nou_pdf/")## [1] "nou199419940009000dddpdfa.pdf" "nou199519950005000dddpdfa.pdf"
## [3] "nou200320030032000dddpdfs.pdf" "nou200820080014000dddpdfs.pdf"
## [5] "nou200920090019000dddpdfs.pdf" "nou201220120002000dddpdfs.pdf"
## [7] "nou201620160008000dddpdfs.pdf"
.pdf-filenetextreadr::read_pdf()library(textreadr)
# Lager objekt for filbane til alle pdfene
nou_pdfer <- list.files("./scrape/nou_pdf/", full.names = TRUE)
# Gå gjennom hver fil og...
nou_tekst <- lapply(nou_pdfer, function(x){
# ... les pdfen og gjør det om til en tibble
read_pdf(x) %>% tibble()
})
# Viser de første 4 radene på listeelement 1
nou_tekst[[1]] %>%
head(., 4)## # A tibble: 4 × 3
## page_id element_id text
## <int> <int> <chr>
## 1 1 1 "NORGES OFFENTLIGE UTREDNINGER\n NOU 19…
## 2 2 1 "Til Utenriksdepartementet\nHurtigbåtutvalget som ble oppn…
## 3 3 1 "NOU 1994:9\nKapittel 1 Om sikkerhet og forhold so…
## 4 4 1 "NOU 1994:9\nKapittel 1 Om sikkerhet og forhold som …
.txt# Fra 1 til 7 (antall NOUer) ...
lapply(1:length(nou_tekst), function(x){
tmp_tekst <- nou_tekst[[x]] %>% # ...trekk ut listeelement x (1:7)
summarize(tekst = str_c(text, # ...og slå sammen teksten til én tekstbolk
collapse = " "))
txt_file_out <- nou_pdfer[x] %>% # Trekk ut filbane for x
str_extract("nou[0-9]+(.*?)\\.pdf") %>% # Trekk ut bare filnavn for filbanen til x
str_remove("\\.pdf") # Fjern ".pdf" fra filbanen til x
writeLines(tmp_tekst$tekst, # Skriv teksten til en .txt fil
str_c("./scrape/nou_txt/", # som skal lagres i mappen ./scrape/nou_txt/
txt_file_out, # med navnet vi laget over
".txt")) # og .txt suffix
})… men husk hypotesen:
Skandinaviske land blir nevnt oftere enn andre land i NOUer fra Utenriksdepartementet
OBS!
| Dependent variable: | |
| n | |
| Skand. land | 168.631*** |
| (52.106) | |
| Konstantledd | 34.569*** |
| (8.884) | |
| Observations | 172 |
| Adjusted R2 | 0.052 |
| Note: | p<0.1; p<0.05; p<0.01 |
/tale/xxxx/Ca. 4 timer kjøretid
# Lager en vektor med alle filnavn
virkord_filer <- list.files("./crawl/virksommeord.no-101413",
full.names = TRUE)
# Viser de første filene i vektoren...
head(virkord_filer)## [1] "./crawl/virksommeord.no-101413/1 .html"
## [2] "./crawl/virksommeord.no-101413/10 .html"
## [3] "./crawl/virksommeord.no-101413/100 .html"
## [4] "./crawl/virksommeord.no-101413/1000 .html"
## [5] "./crawl/virksommeord.no-101413/1001 .html"
## [6] "./crawl/virksommeord.no-101413/1002 .html"
## [1] 5100
# Leser inn alle filene fra kravlingen
virkord_html <- lapply(virkord_filer, rvest::read_html)
# Går gjennom alle filene med preprosessering
virkord_data <- lapply(1:length(virkord_html), function(x){
tmp_tekst <- virkord_html[[x]] %>%
html_elements("div[class='document'] > p") %>% # Trekker ut elementene <div class="document"> etterfulgt av <p>
html_text() # Konverterer til tekst
if(identical(character(), tmp_tekst)){ # Hvis teksten er tom...
tmp_tekst <- virkord_html[[x]] %>% #
html_elements("tr[valign='top']") %>% # ...trekker jeg ut <tr valign="top>
html_text() # og gjør om til tekst
}
if(identical(character(), tmp_tekst)){ # Hvis teksten fortsatt er tom...
tmp_tekst <- virkord_html[[x]] %>% #
html_elements("div[class='document'] > h3") %>% # ...trekker jeg ut elementene <div class="document"> etterfulgt av <h3>
html_text() %>% # ...gjør om til tekst
str_split(., "\\n") %>% # ...splitter opp i linjer
unlist() # ... og konverterer fra liste til vektor
}
# Trekker ut forfatternavn
tmp_forfatter <- virkord_html[[x]] %>%
html_elements("div[class='tale-header'] > ul[class='byline'] > li > a") %>%
html_text() %>%
str_replace_all(., "\\s+", " ") %>%
.[1]
# Trekker ut link til forfatterside
tmp_forfatter_link <- virkord_html[[x]] %>%
html_elements("div[class='tale-header'] > ul[class='byline'] > li > a") %>%
html_attr("href") %>%
.[which(str_detect(., "person"))]
# Trekker ut tittel
tmp_tittel <- virkord_html[[x]] %>%
html_elements("div[class='tale-header'] > h1") %>%
html_text() %>%
str_replace_all(., "\\s+", " ")
# Setter alt sammen til en tibble
tmp_data <- tibble(
tittel = tmp_tittel,
forfatter = tmp_forfatter,
forfatter_link = tmp_forfatter_link,
avsnitt = 1:length(tmp_tekst),
tekst = tmp_tekst
)
return(tmp_data)
})
# Binder så sammen alle tibbles i listen "virkord_data"
# Til å være én tibble
virkord <- bind_rows(virkord_data)
# save(virkord, file = "./crawl/virksommeord.rda")## # A tibble: 6 × 5
## tittel forfa…¹ forfa…² avsnitt tekst
## <chr> <chr> <chr> <int> <chr>
## 1 "200 år som sentralbank i en liten, åpen økonom… Øystei… /perso… 72 "Fry…
## 2 "Vårt innsatsforsvar - i en relevant Allianse" Anne-G… /perso… 178 "Vi …
## 3 "Økonomiske perspektiver" Øystei… /perso… 66 "Jeg…
## 4 "«Å skape brorskap» " Grete … /perso… 8 "Alt…
## 5 "Folkefrihed og Folkeforening" Marcus… /perso… 22 "Man…
## 6 "Vilje til endringer og nye løsninger" Harald… /perso… 83 "Reg…
## # … with abbreviated variable names ¹forfatter, ²forfatter_link
"Page":1,
"Hits":20, "TotalHits":71, osvdownload.file() er din vennrobots.txt eksisterer på de fleste
nettsider
## [1] "User-agent: *"
## [2] "Disallow: /tegneserier/salesposter"
## [3] "Disallow: /poll"
## [4] ""
## [5] "user-agent: Googlebot-News"
## [6] "disallow: /annonsorinnhold/"
## [7] "disallow: /kommersielt-innhold/"
## [8] "disallow: /innstikk/"
## [9] "disallow: /?embed=true"
## [10] "disallow: /arkiv/"
## [11] "disallow: /front/"
## [12] "disallow: /ads/prewarm/"
## [13] "disallow: /adblock-survey/"
## [14] ""
## [15] "Sitemap: https://www.vg.no/sitemap/files/articles-48hrs.xml"
## [16] "Sitemap: https://www.vg.no/sitemap/sitemap.xml"
Høyland & Søyland (2019):
convert -density 300x300 -shave 10x100;
not_noisy.png not_noisy_clean1.png
convert not_noisy_clean1.png -normalize ;
not_noisy_clean2.png
convert not_noisy_clean2.png ;
-connected-components 4 -threshold 0 -negate;
not_noisy_clean3.png
convert not_noisy_clean2.png;
-define connected-components:area-threshold=15;
-connected-components 4 -threshold 0 -negate;
not_noisy_clean4.png
convert not_noisy_clean3.png not_noisy_clean4.png;
-compose minus -composite;
not_noisy_clean5.png
convert not_noisy_clean2.png;
\( -clone 0 -negate -fill white -colorize 100% \) ;
not_noisy_clean5.png -compose Blend -composite;
not_noisy_clean6.png
convert not_noisy_clean6.png;
-fill black -opaque "#FF00FF" -morphology Erode Disk:0.5;
not_noisy_cleaned.png
# https://github.com/tesseract-ocr/tesseract
tesseract not_noisy_cleaned.png tekst
head -n 10 tekst.txt## [1] "er misbruk. Men man har reglerne; det er"
## [2] "nødvendig for en apoteker at levere efter"
## [3] "recept. Selvfølgelig, hvis han er viss paa,"
## [4] "at det er et misbruk, er. det hans pligt at"
## [5] "negte. Men man stiller disse samvittighets-"
## [6] "fulde apotekere i en uholdbar, vanskelig"
## [7] "stilling ved de nuværende regler."
## [1] "-Pwresldonbene: v Medi mmsyh då aperdkkktes"
## [2] "løs inamis psangterrmeil pesosiskeh beer ajberaide"
## [3] "9 gjør 2: 3berdosn m jpas, st hen haddetenkt"
## [4] "aa saDNg OD ,Gftennisk"
## [5] "sol næste vike: hadde. præsidenten"
## # A tibble: 6 × 3
## speech_id name_fixed speech
## <chr> <chr> <chr>
## 1 speech210284 Robert Sæther "Når den bevilgning som blir gitt und…
## 2 speech096962 Ole Andor Hoel "Jeg forlangte ordet for at gjøre opm…
## 3 speech107950 Martinus Nikolai Sivertsen "Komiteens ordfører oplyste, at Krist…
## 4 speech113775 Anfin Øen "Del næste talarane hev upptil 2 minu…
## 5 speech004338 Peter Valeur "Jeg har den opfatning, at der er gjo…
## 6 speech009899 Alfred Eriksen "Jeg fremholdt igaar, at dersom vort …
## features
## docs det har jord lærere behandling park
## speech006356 1 0 0 0 0 0
## speech010491 3 2 9 0 0 0
## speech012336 21 19 0 5 0 0
## speech015337 2 0 0 0 1 0
## speech020126 10 5 0 0 0 5
## speech023230 8 5 0 0 1 0
robots.txtForbehandling av tekst 1 (uke 36)
Forbehandling av tekst 2 (uke 37)
Bruke API (Stortinget) (uke 38)